package org.zfes.snowier.cloud.zbss.pmp.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.collections.ListUtils;
import org.zfes.snowier.auth.shiro.util.SecurityUtil;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpProjectUpdateDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpProjectVersionCreateDto;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProjectGroup;
import org.zfes.snowier.cloud.zbss.pmp.service.IpmpProjectGroupService;
import org.zfes.snowier.core.data.ComboboVo;
import org.zfes.snowier.core.data.DataSet;
import org.zfes.snowier.core.data.Record;
import org.zfes.snowier.core.exceptions.ServiceLogicalException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.zfes.snowier.core.util.ZBeanUtil;
import org.zfes.snowier.core.util.ZDateUtil;
import org.zfes.snowier.core.util.ZObjectUtil;
import org.zfes.snowier.core.util.ZStrUtil;

import com.google.common.collect.Lists;

import org.zfes.snowier.core.util.AppCtxUtil;
import org.zfes.snowier.core.util.ZAlert;
import org.zfes.snowier.core.util.ZAssert;
import org.zfes.snowier.common.dao.params.ParamMap;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpCloudMemberService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpProjectService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpProjectVersionService;
import org.zfes.snowier.biz.factory.AuthManagerFactory;
import org.zfes.snowier.biz.manager.ISnowierSysAndAuthManager;
import org.zfes.snowier.cloud.zbss.pmp.dao.PmpProjectMapper;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpProjectCreateDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpProjectGroupDetailDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpProjectMemberDto;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpCloudMember;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProject;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProjectVersion;

import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class PmpProjectServiceImpl implements IPmpProjectService{
 	@Autowired
	private PmpProjectMapper pmpProjectMapper;
	
	@Autowired
	private IPmpCloudMemberService pmpCloudMemberService;

	@Autowired
	private IPmpProjectVersionService pmpProjectVersionService;

	@Autowired
    private IpmpProjectGroupService pmpProjectGroupService;

	@Transactional(rollbackFor=Exception.class)
 	@Override
	public void createPmpProject(PmpProjectCreateDto pmpProjectDto) {
	    //创建一个新项目
        ZBeanUtil.validateBean(pmpProjectDto);
        PmpProject pmpProject=new PmpProject();

        //赋值
        ZBeanUtil.copy(pmpProjectDto, pmpProject, true);
        
        PmpCloudMember pm=pmpCloudMemberService.loadPmpCloudMemberById(pmpProjectDto.getPmUserId()).orElseThrow(()->new ServiceLogicalException("未查询到该用户"));
        ZAssert.equals(pm.getStatus(), Byte.valueOf("1"), "【PM】用户状态错误");
        
        
        selectByName(pmpProjectDto.getName()).ifPresent(val->ZAlert.newSLE( "该项目名已存在"));
        
        pmpProject.setStatus(Byte.valueOf("0"));
        pmpProject.setMemberCount(Integer.valueOf(0));
        pmpProject.setPmUserName(pm.getUserName());
        pmpProject.setUpdatetime(ZDateUtil.newDate()).setCreatetime(ZDateUtil.newDate());
        
        ZBeanUtil.setCreateInfo(pmpProject);
        ZBeanUtil.validateBean(pmpProject);

        pmpProjectMapper.insertSelective(pmpProject);
        
        pmpProjectGroupService.addOnePmpProjectGroupMember(pmpProject.getId(),pm.getId(),Byte.valueOf("3"));
        
        if(ZStrUtil.hasText(pmpProjectDto.getDevIds())) {
        	ZStrUtil.splitLong(pmpProjectDto.getDevIds()).forEach(va -> {
        		pmpProjectGroupService.addOnePmpProjectGroupMember(pmpProject.getId(),va,Byte.valueOf("1"));
        	});
        	
        }
        if(ZStrUtil.hasText(pmpProjectDto.getTestIds())) {
        	ZStrUtil.splitLong(pmpProjectDto.getTestIds()).forEach(va -> {
        		pmpProjectGroupService.addOnePmpProjectGroupMember(pmpProject.getId(),va,Byte.valueOf("2"));
        	});
        }
       
        Long vid=pmpProjectVersionService.createPmpProjectVersion(new PmpProjectVersion(pmpProject.getId(), "V1.0.0", "初始版本"));
		pmpProjectMapper.updateVersion(pmpProject.getId(),vid,"V1.0.0");

	}

    @Transactional(rollbackFor=Exception.class)
    @Override
    public  Optional<PmpProject> selectByName(String name) {
		
		return Optional.ofNullable(pmpProjectMapper.selectByName(name));
	}

	@Transactional(rollbackFor=Exception.class)
    @Override
    public void updatePmpProject(PmpProjectUpdateDto pmpProjectDto) {
	    ZBeanUtil.validateBean(pmpProjectDto);

        PmpProject project=loadPmpProjectById( pmpProjectDto.getId()).orElseThrow(()->ZAlert.newSLE("未查询到该项目数据"));
		
        Optional<PmpProject> projOp= selectByName(pmpProjectDto.getName()) ;
        if(projOp.isPresent()) {
        	ZAssert.equals(projOp.get().getId(), pmpProjectDto.getId(), "该项目名已经存在");
        }
        
        ZBeanUtil.copy(pmpProjectDto, project, true);
		
        pmpProjectMapper.updateByPrimaryKeySelective(project);
        
    }

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updatePmpProjectMemberCount(Long id, Integer count) {
		ZAssert.notNull(id, "请选择要操作的数据");
		ZAssert.notNull(count, "请输入更新人数");
		
		 PmpProject project=loadPmpProjectById( id).orElseThrow(()->ZAlert.newSLE("未查询到该项目数据"));

		 if(!Stream.of(new Byte[] {0,1,3}).anyMatch(val->val.equals(project.getStatus()))) {
				ZAlert.serviceLogicalError("项目当前状态不允许更新人数");
			}
		//#0未开始，1进行中，2结束，3暂停中，-1删除	
		
		pmpProjectMapper.updateMemberCount(id,count+project.getMemberCount());

	}


	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updatePmpProjectVersion(Long id,Long versionId) {
		PmpProjectVersion version=pmpProjectVersionService.loadPmpProjectVersionById(versionId).orElseThrow(()->ZAlert.newSLE("未查询到该项目版本数据"));
		ZAssert.equals(version.getStatus(), Byte.valueOf("1"), "该版本不存在或者已删除");
		
		pmpProjectMapper.updateVersion(id,version.getId(),version.getVersion());
		
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<PmpProject> loadPmpProjectById(Long id) {
		if(id!=null){
			return Optional.ofNullable(pmpProjectMapper.selectByPrimaryKey(id));
		}
		return Optional.empty();
	}
	

	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<ComboboVo> loadComboboVo(boolean firstEmpty) {
		List<ComboboVo> voList=pmpProjectMapper.selectComboboVo(Byte.valueOf("1"));
		if(firstEmpty) {
			voList.add(0, ComboboVo.newEmptyFirst());
		}
		return voList;
	}
	
//#0未开始，1进行中，2结束，3暂停中，4关闭-1删除 #
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setPmpProjectStatus(Long id, Byte status) {
		ZAssert.notNull(id, "请选择要操作的数据");
		ZAssert.notNull(status, "状态参数错误");
		if(!Stream.of(new Byte[] {0,1,2,3,4,-1}).anyMatch(val->val.equals(status))) {
			ZAlert.serviceLogicalError("状态参数错误");
		}
		pmpProjectMapper.updateStatus( id,  status) ;
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public DataSet loadPmpProjectDataSet(Map<String, Object> params) {
		ParamMap pm=ParamMap.filterParam(params);
        pm.getObj("name").ifPresent(v->pm.updateParam("name", "%"+v+"%"));
		DataSet ds=DataSet.newDS2(pmpProjectMapper.selectListCount(pm), pmpProjectMapper.selectMapListPage(pm));
		return ds;
	}

	//测试人员 开发人员参与项目列表
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<PmpProjectMemberDto> loadUserPmpProjectList(Long userId) {
        List<PmpProjectGroup> projectGroupList = pmpProjectGroupService.loadPmpProjectGroupByUseId(userId);
        if(ZObjectUtil.isEmpty(projectGroupList)) {
        	return Lists.newArrayList();
        }
       Map<Long,Byte> userRoleInGroup= projectGroupList.stream().collect(Collectors.toMap(PmpProjectGroup::getProjectId, PmpProjectGroup::getUserType));
        
       List<PmpProject> projectList=pmpProjectMapper.selectByIds(projectGroupList.stream().map(val->val.getProjectId()).collect(Collectors.toList()));
       
       

       return  projectList.stream().map(proj-> new PmpProjectMemberDto(proj,userRoleInGroup.get(proj.getId()))).collect(Collectors.toList());
       
    }

}